﻿using System.Collections.Generic;
using Metro.Kashikoi.Service.Common.Entity;
using Metro.Kashikoi.Service.Location.Business;
using Metro.Kashikoi.Service.Location.Entity;
using Metro.Kashikoi.ServiceContract;
using Metro.Kashikoi.ServiceContract.Location;
using Metro.Kashikoi.ServiceContract.Storage;

namespace Metro.Kashikoi.Service.Location.Service
{
    /// <summary>
    /// This class implements the interface <c>ILocationService</c>.
    /// </summary>
    public class LocationService : ILocationService
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="LocationService"/> class.
        /// </summary>
        public LocationService()
        {
            this.Facade = new Facade();
            this.Factory = new UnitOfWorkFactory();
        }

        private IStorageService StorageService { get { return ServiceBus.GetService<IStorageService>(); } }

        private IFacade Facade { get; set; }
        private IUnitOfWorkFactory Factory { get; set; }

        /// <summary>
        /// Creates the organization.
        /// </summary>
        /// <param name="organization">The organization.</param>
        /// <returns>
        /// The newly created organization.
        /// </returns>
        public Organization CreateOrganization(Organization organization)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.CreateOrganization(ctx, organization);
                ctx.SaveChanges();
            }
            return organization;
        }

        /// <summary>
        /// Updates the organization.
        /// </summary>
        /// <param name="organization">The organization.</param>
        public void UpdateOrganization(Organization organization)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.UpdateOrganization(ctx, organization);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Deleles the organization.
        /// </summary>
        /// <param name="organizationId">The organization id.</param>
        public void DeleleOrganization(int organizationId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                IList<int> deletedStockArea = new List<int>();
                Facade.DeleleOrganization(ctx, organizationId, deletedStockArea);
                // Delete inventoies of organization.
                StorageService.DeleteInventoriesOfStockAreas(deletedStockArea);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Gets the default organization.
        /// </summary>
        /// <returns>
        /// The default organization.
        /// </returns>
        public Organization GetDefaultOrganization()
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                return Facade.GetDefaultOrganization(ctx);
            }
        }

        /// <summary>
        /// Gets the organization.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>
        /// The organization with the specific name.
        /// </returns>
        public Organization GetOrganization(string name)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                return Facade.GetOrganization(ctx, name);
            }
        }

        /// <summary>
        /// Creates the facility.
        /// </summary>
        /// <param name="facility">The facility.</param>
        /// <param name="organizationId">The organization id.</param>
        /// <returns>
        /// The newly created facility.
        /// </returns>
        public Facility CreateFacility(Facility facility, int organizationId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.CreateFacility(ctx, facility, organizationId);
                ctx.SaveChanges();
            }
            return facility;
        }

        /// <summary>
        /// Updates the facility.
        /// </summary>
        /// <param name="facility">The facility.</param>
        public void UpdateFacility(Facility facility)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.UpdateFacility(ctx, facility);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Deletes the facility.
        /// </summary>
        /// <param name="facilityId">The facility id.</param>
        public void DeleteFacility(int facilityId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                IList<int> deletedStockArea = new List<int>();
                Facade.DeleteFacility(ctx, facilityId, deletedStockArea);
                // Delete the inventories of the facility.
                StorageService.DeleteInventoriesOfStockAreas(deletedStockArea);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Creates the unit.
        /// </summary>
        /// <param name="unit">The unit.</param>
        /// <param name="facilityId">The facility id.</param>
        /// <returns>
        /// The newly created unit.
        /// </returns>
        public Unit CreateUnit(Unit unit, int facilityId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.CreateUnit(ctx, unit, facilityId);
                ctx.SaveChanges();
            }
            return unit;
        }

        /// <summary>
        /// Updates the unit.
        /// </summary>
        /// <param name="unit">The unit.</param>
        public void UpdateUnit(Unit unit)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.UpdateUnit(ctx, unit);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Deletes the unit.
        /// </summary>
        /// <param name="unitId">The unit id.</param>
        public void DeleteUnit(int unitId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                IList<int> deletedStockArea = new List<int>();
                Facade.DeleteUnit(ctx, unitId, deletedStockArea);
                // Delete the inventories of the unit.
                StorageService.DeleteInventoriesOfStockAreas(deletedStockArea);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Creates the stock area.
        /// </summary>
        /// <param name="stockArea">The stock area.</param>
        /// <param name="unitId">The unit id.</param>
        /// <returns>
        /// The newly created stock area.
        /// </returns>
        public StockArea CreateStockArea(StockArea stockArea, int unitId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.CreateStockArea(ctx, stockArea, unitId);
                ctx.SaveChanges();
            }
            return stockArea;
        }

        /// <summary>
        /// Updates the stock area.
        /// </summary>
        /// <param name="stockArea">The stock area.</param>
        public void UpdateStockArea(StockArea stockArea)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.UpdateStockArea(ctx, stockArea);
                ctx.SaveChanges();
            }
        }

        /// <summary>
        /// Deletes the stock area.
        /// </summary>
        /// <param name="stockAreaId">The stock area id.</param>
        public void DeleteStockArea(int stockAreaId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                Facade.DeleteStockArea(ctx, stockAreaId);
                // Delete the inventories of the stock area.                
                StorageService.DeleteInventoriesOfStockAreas(new int[] { stockAreaId });
                ctx.SaveChanges();
            }
        }


        /// <summary>
        /// Gets the stock area.
        /// </summary>
        /// <param name="stockAreaId">The stock area id.</param>
        /// <returns>
        /// The stock area.
        /// </returns>
        public StockArea GetStockArea(int stockAreaId)
        {
            using (IUnitOfWork ctx = Factory.GetContext<ILocationService>())
            {
                return Facade.GetStockArea(ctx, stockAreaId);
            }
        }
    }
}
